package http;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class DefaultThreadPool<Job extends Runnable> implements ThreadPool<Job> {

    private static final int MAX_WORKER_NUMBERS=10;
    private static final int DEAFULT_WORKER_NUMBERS=5;
    private static final int MIN_WORKER_NUMBERS=1;
    private final LinkedList<Job> jobs=new LinkedList<Job>();
    private final List<Worker> workers= Collections.synchronizedList(new ArrayList<>());
    private int workNum=DEAFULT_WORKER_NUMBERS;
    private AtomicLong threadNum=new AtomicLong();
    public DefaultThreadPool(){
        initializeWorkers(DEAFULT_WORKER_NUMBERS);
    }
    public DefaultThreadPool(int num){
        workNum=num>MAX_WORKER_NUMBERS?MAX_WORKER_NUMBERS:num<MIN_WORKER_NUMBERS?MIN_WORKER_NUMBERS:num;
        initializeWorkers(this.workNum);
    }
    @Override
    public void execute(Job job) {
        if(job!=null){
            synchronized (jobs){
                jobs.addLast(job);
                jobs.notify();
            }
        }
    }

    @Override
    public void shutdown() {
        for(Worker worker:workers){
            worker.shutdown();
        }
    }

    @Override
    public void addWorkers(int num) {
        synchronized (jobs){
            if(num+this.workNum>MAX_WORKER_NUMBERS){
                num=MAX_WORKER_NUMBERS-this.workNum;
            }
            initializeWorkers(num);
            this.workNum+=num;
        }
    }

    @Override
    public void removeWorkers(int num) {
        synchronized (jobs){
            if(num>=this.workNum){
                throw new IllegalArgumentException("begond workNum");
            }
            int count=0;
            while (count<num){
                Worker worker=workers.get(count);
                if(workers.remove(worker)){
                    worker.shutdown();
                    count++;
                }
            }
            this.workNum-=count;
        }
    }

    @Override
    public int getJobSize() {
        return jobs.size();
    }
    private void initializeWorkers(int num){
        for (int i = 0; i < num; i++) {
            Worker worker=new Worker();
            workers.add(worker);
            Thread thread=new Thread(worker,"ThreadPool-Worker-"+threadNum.incrementAndGet());

            thread.start();
        }
    }
    class Worker implements Runnable{
        private volatile boolean running=true;
        @Override
        public void run() {
            while (running){
                Job job=null;
                synchronized (jobs){
                    while (jobs.isEmpty()){
                        try {
                            jobs.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            return;
                        }
                    }
                    job=jobs.removeFirst();
                    System.out.println(Thread.currentThread().getName()+"我执行的");
                }
                if(job!=null){
                    job.run();
                }
            }
        }
        public void shutdown(){
            running=false;
        }
    }

    public static void main(String[] args) {
        DefaultThreadPool<Runnable> runnableDefaultThreadPool = new DefaultThreadPool<>();
        for (int i = 0; i < 10; i++) {
            runnableDefaultThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

interface ThreadPool<Job extends Runnable>{
    void execute(Job job);
    void shutdown();
    void addWorkers(int num);
    void removeWorkers(int num);
    int getJobSize();
}
